namespace SimpleWebServices.Data
{
    using System;

    public struct Token
    {
        private static readonly Token _empty = Guid.Empty;

        private Guid _value;

        public Token(Guid value)
        {
            this._value = value;
        }

        public Token(string value)
        {
            if (null == value)
            {
                throw new ArgumentNullException("value");
            }
            else if (0 == value.Length)
            {
                value = Token.Empty.ToString();
            }

            this._value = new Guid(value);
        }

        public static Token Empty
        {
            get
            {
                return _empty;
            }
        }

        public bool IsEmpty
        {
            get
            {
                return this == Token.Empty;
            }
        }

        public static bool operator ==(Token obj, Token comparand)
        {
            return obj.Equals(comparand);
        }

        public static bool operator !=(Token obj, Token comparand)
        {
            return !obj.Equals(comparand);
        }

        public static implicit operator Token(Guid value)
        {
            return new Token(value);
        }

        public static implicit operator Guid(Token token)
        {
            return token.ToGuid();
        }

        public static implicit operator Token(string value)
        {
            return new Token(value);
        }

        public static implicit operator string(Token token)
        {
            return token.ToString();
        }

        public static Token New()
        {
            return Guid.NewGuid();
        }

        public Guid ToGuid()
        {
            return this._value;
        }

        public override bool Equals(object obj)
        {
            bool result = false;

            if (!object.ReferenceEquals(null, obj))
            {
                try
                {
                    Token cast = (Token)obj;
                    result = this.ToGuid().Equals(cast.ToGuid());
                }
                catch (InvalidCastException)
                {
                }
            }

            return result;
        }

        public override int GetHashCode()
        {
            return this._value.GetHashCode();
        }

        public override string ToString()
        {
            return this._value.ToString();
        }
    }
}